#ifndef _THREAD_HPP_
#define _THREAD_HPP_
#include <iostream>
#include<string>
#include<functional>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>
#include<sys/types.h>
namespace My_thread{
    using func_t = std::function<void(std::string)>;
    static int num_threads = 0;
    enum class STATUS{//线程状态
        NEW,
        RUNNING,
        STOP
    };
    class Thread{
        private:
            static void* Routine(void* arg)//静态成员函数没有this指针(属于整个类)，可以适配pthread_create中的函数指针参数
            {
                
                Thread* p = static_cast<Thread*>(arg);
                p->_status = STATUS::RUNNING;
                p->_func(p->GetName());//重入函数后，执行各线程的任务
                return nullptr;
            }
        public:
            Thread(func_t func):_func(func),_status(STATUS::NEW),_is_joinable(true)
            {
                _name = "Thread-"+std::to_string(num_threads);
                num_threads++;
                _pid = getpid();
            }
            ~Thread()
            {
            
            }
            bool Run()
            {
                if(_status != STATUS::RUNNING){
                    _status = STATUS::RUNNING;
                    int n = pthread_create(&_tid,nullptr,Routine,this);
                    return true;
                }
                return false;
            }
            bool Stop()
            {
                if(_status == STATUS::RUNNING){
                    int n = pthread_cancel(_tid);
                    if(n!= 0)return false;
                    _status = STATUS::STOP;
                    return true;
                }
                return false;
            }
            bool Join()
            {
                if(_is_joinable){
                    int n = pthread_join(_tid,nullptr);
                    if(n!= 0)return false;    
                    _status = STATUS::STOP;
                    return true;
                }
                return false;
            }
            void Detach()
            {
                _is_joinable = false;
                pthread_detach(_tid);
            }
            bool IsJoinable(){return _is_joinable;}
            std::string GetName(){return _name;} //线程名

        private:
            std::string _name;
            pthread_t _tid;//线程id
            pid_t _pid;
            bool _is_joinable;//线程是否分离（默认不是）
            func_t _func;
            STATUS _status;
    };

    class Mutex{//互斥锁    
        public:
            Mutex()
            {
                int n = pthread_mutex_init(&_lock,nullptr);
            }
            Mutex(const Mutex&) = delete;//禁止拷贝构造函数
            Mutex& operator=(const Mutex&) = delete;//禁止拷贝赋值函数
            ~Mutex()
            {
                int n = pthread_mutex_destroy(&_lock);
            }
            void Lock()
            {
                int n = pthread_mutex_lock(&_lock); 
            }
            void Unlock()
            {
                int n = pthread_mutex_unlock(&_lock);
            }
            pthread_mutex_t* GetLock()
            {
                return &_lock;
            }
        private:
            pthread_mutex_t _lock;
    };

    class LockGuard{//锁管理器
        public:
            LockGuard(Mutex& m):_mutex(m)
            {
                _mutex.Lock();
            }
            ~LockGuard()
            {
                _mutex.Unlock();
            }
        private:
            Mutex& _mutex;
    };
    class Cond{//条件变量
        public:
            Cond()
            {
                int n = pthread_cond_init(&_cond,nullptr);
            }
            void Wait(Mutex& m)
            {
                int n = pthread_cond_wait(&_cond,m.GetLock());
            }
            void Signal()
            {
                int n = pthread_cond_signal(&_cond);
            }
            void Broadcast()
            {
                int n = pthread_cond_broadcast(&_cond);
            }
            ~Cond()
            {
                int n = pthread_cond_destroy(&_cond);
            }
        private:
            pthread_cond_t _cond;
    };

}

#endif